// File Name: oled_interface.c
// Author: kukukukuku~
// Date: 2024-12-23

#include "./OLED/inc/oled_interface.h"

/**
 * @brief   OLED指令初始化
 * @param   None
 * @retval  None
 * @note    None
*/
void oled_code_init(void)
{
    oled_send_data(0xAE, OLED_SEND_CMD);
        
    oled_send_data(0x40, OLED_SEND_CMD);
    oled_send_data(0xB0, OLED_SEND_CMD);
    
    oled_send_data(0x81, OLED_SEND_CMD);
    oled_send_data(0xFA, OLED_SEND_CMD);

    oled_send_data(0xC8, OLED_SEND_CMD);
    oled_send_data(0xA1, OLED_SEND_CMD);
    
    oled_send_data(0xA6, OLED_SEND_CMD);
    
    oled_send_data(0xA8, OLED_SEND_CMD);
    oled_send_data(0x1F, OLED_SEND_CMD);
    
    oled_send_data(0xD3, OLED_SEND_CMD);
    oled_send_data(0x00, OLED_SEND_CMD);
    
    oled_send_data(0xD5, OLED_SEND_CMD);
    oled_send_data(0xF0, OLED_SEND_CMD);
    
    oled_send_data(0xD9, OLED_SEND_CMD);
    oled_send_data(0x22, OLED_SEND_CMD);
    
    oled_send_data(0xDA, OLED_SEND_CMD);
    oled_send_data(0x02, OLED_SEND_CMD);
    
    oled_send_data(0xDB, OLED_SEND_CMD);
    oled_send_data(0x49, OLED_SEND_CMD);
    
    oled_send_data(0x8D, OLED_SEND_CMD);
    oled_send_data(0x14, OLED_SEND_CMD);
    
    oled_send_data(0xAF, OLED_SEND_CMD);
}


/**
 * @brief   OLED设置坐标
 * @param   x:  横坐标
 * @param   y:  纵坐标
 * @retval  None
 * @note    静态
*/
static void oled_set_position(const uint8_t x, const uint8_t y)
{
    if(x > OLED_COLUMN_MAX - 8 || y > OLED_PAGE_MAX - 1)
        return;
    
    oled_send_data(0xB0 + y, OLED_SEND_CMD);
    oled_send_data((x & 0xF0) >> 4 | 0x10, OLED_SEND_CMD);
    oled_send_data(x & 0x0F, OLED_SEND_CMD);
}


/**
 * @brief   OLED开显示
 * @param   None
 * @retval  None
 * @note    None
*/
void oled_display_on(void)
{
    oled_send_data(0x8D, OLED_SEND_CMD);
    oled_send_data(0x14, OLED_SEND_CMD);
    oled_send_data(0xAF, OLED_SEND_CMD);
}


/**
 * @brief   OLED关显示
 * @param   None
 * @retval  None
 * @note    None
*/
void oled_display_off(void)
{
    oled_send_data(0x8D, OLED_SEND_CMD);
    oled_send_data(0x10, OLED_SEND_CMD);
    oled_send_data(0xAE, OLED_SEND_CMD);
}


/**
 * @brief   OLED清屏
 * @param   None
 * @retval  None
 * @note    None
*/
void oled_clear(void)
{
    for(uint8_t i = 0; i < OLED_PAGE_MAX; i++)
    {
        oled_send_data(0xB0 + i, OLED_SEND_CMD);
        oled_send_data(0x00, OLED_SEND_CMD);
        oled_send_data(0x10, OLED_SEND_CMD);
        
        for(uint8_t j = 0; j < OLED_COLUMN_MAX; j++)
            oled_send_data(0x00, OLED_SEND_DATA);
    }
}


/**
 * @brief   OLED显示一个8x16字符
 * @param   x:              横坐标
 * @param   y:              纵坐标
 * @param   fontSource:     字库源
 * @param   fontSourceSize: 字库源大小
 * @param   ch:             要显示的字符
 * @param   mode:           显示模式
 *                          @arg 0: 正相
 *                          @arg 1: 反相
 * @retval  None
 * @note    None
*/
void oled_show_char_8x16(const uint8_t x, const uint8_t y, const uint8_t * const fontSource,
                         const uint16_t fontSourceSize, const uint8_t ch, const uint8_t mode)
{
    uint16_t index = 0;
    
    if(fontSource == NULL || fontSourceSize == 0 || ch > 127 || x > OLED_COLUMN_MAX - 8 || y > OLED_PAGE_MAX - 2)
        return;
    
    //一个字符占2页
    for(uint8_t i = 0; i < 2; i++)
    {
        oled_set_position(x, y + i);
        
        //一个字符在每页占8列
        for(uint8_t j = 0; j < 8; j++)
        {
            index = (ch * 16) + (8 * i) + j;
            
            if(index >= fontSourceSize)
                return;
            
            oled_send_data(mode ? ~fontSource[index] : fontSource[index], OLED_SEND_DATA);
        }
    }
}


/**
 * @brief   OLED显示8x16字符串
 * @param   x:              横坐标
 * @param   y:              纵坐标
 * @param   fontSource:     字库源
 * @param   fontSourceSize: 字库源大小
 * @param   str:            要显示的字符串
 * @param   mode:           显示模式
 *                          @arg 0: 正相
 *                          @arg 1: 反相
 * @retval  None
 * @note    None
*/
void oled_show_str_8x16(const uint8_t x, const uint8_t y, const uint8_t * const fontSource,
                        const uint16_t fontSourceSize, const uint8_t * const str, const uint8_t mode)
{
    uint8_t xx = x, yy = y;
    uint8_t i = 0;
    
    if(fontSource == NULL || fontSourceSize == 0 || str == NULL || x > OLED_COLUMN_MAX - 8 || y > OLED_PAGE_MAX - 2)
        return;
    
    while(str[i])
    {
        if(xx > OLED_COLUMN_MAX - 8)
        {
            xx = 0;
            yy += 2;
        }
        
        if(yy > OLED_PAGE_MAX - 2)
            return;
        
        oled_show_char_8x16(xx, yy, fontSource, fontSourceSize, str[i++], mode);
        
        xx += 8;
    }
}
